package com.walkline.notes;

import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

import javax.microedition.io.HttpConnection;

import net.rim.device.api.io.transport.ConnectionFactory;
import net.rim.device.api.util.Comparator;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;
import org.json.me.JSONTokener;

import com.walkline.app.NotesAppConfig;
import com.walkline.notes.dao.NotesNote;
import com.walkline.notes.dao.NotesNotes;
import com.walkline.notes.inf.Note;
import com.walkline.notes.inf.Notes;
import com.walkline.util.Function;
import com.walkline.util.network.HttpClient;

public class NotesSDK
{
	protected ConnectionFactory _cf;
	protected HttpClient _http;

	//protected String _appKey = NotesConfig.client_ID;
	//protected String _appSecret = NotesConfig.client_SERCRET;

	public static NotesSDK getInstance()
	{
		return new NotesSDK();
	}

	protected NotesSDK()
	{
		_cf = new ConnectionFactory();
		_cf.setPreferredTransportTypes(NotesAppConfig.preferredTransportTypes);
		_cf.setDisallowedTransportTypes(NotesAppConfig.disallowedTransportTypes);
		_cf.setTimeoutSupported(true);
		_cf.setAttemptsLimit(10);
		_cf.setRetryFactor(2000);
		_cf.setConnectionTimeout(120000);

		_http = new HttpClient(_cf);
	}

	public byte[] doRequestRAW(String path) throws NotesException
	{
		byte[] result = null;
		StringBuffer responseBuffer = null;

		try {
			responseBuffer = checkResponse(_http.doGet(path));				

			if ((responseBuffer == null) || (responseBuffer.length() <= 0)) {result = null;}

			result = responseBuffer.toString().getBytes();
		} catch (Exception e) {throw new NotesException(e.getMessage());}

		return result;
	}

	public Note getSingleNote(JSONObject jo) throws NotesException {return new NotesNote(this, jo);}
	public Note getSingleNote(int id) throws NotesException {return getSingleNote(id, null, null);}
	public Note getSingleNote(final int id, final AsyncCallback listener, final Object state) throws NotesException
	{
		if (listener != null) {
			new Thread() {
				public void run() {
					try {
						Note result = null;
						result = getSingleNote(id);
						listener.onComplete(result);
					} catch (Exception e) {
						listener.onException(e);
					}
				}
			}.start();

			return null;
		} else {
			Note result = null;
			Hashtable params = new Hashtable();

			params.put("id", String.valueOf(id));

			JSONObject jsonObject = doRequest(HttpConnection.GET, NotesConfig.getSingleNote, params);
			if ((jsonObject == null) || (jsonObject.length() <= 0)) {
				result = null;
			} else {
				result = getSingleNote(jsonObject);
			}

			return result;
		}
	}

	public Notes getNotes(JSONObject jo) throws NotesException {return new NotesNotes(this, jo);}
	public Notes getNotes() throws NotesException {return getNotes(null, null);}
	public Notes getNotes(final AsyncCallback listener, final Object state) throws NotesException
	{
		if (listener != null) {
			new Thread() {
				public void run() {
					try {
						Notes result = null;
						result = getNotes();
						listener.onComplete(result);
					} catch (Exception e) {
						listener.onException(e);
					}
				}
			}.start();

			return null;
		} else {
			Notes result = null;
			//Hashtable params = new Hashtable();

			JSONObject jsonObject = doRequest(HttpConnection.GET, NotesConfig.getNotes, null);
			if ((jsonObject == null) || (jsonObject.length() <= 0)) {
				result = null;
			} else {
				result = getNotes(jsonObject);
			}

			return result;
		}
	}




//**************************************************************************************************
//
//             //              //      //    //      ////////////////            //      //        
//             //            //    //  //  //                    //          //  //  //  //        
// //////////  //          //////////  ////        //          //      //        //      //        
//     //    ////////////              //      //  //  //    //    //  //  ////////////  ////////  
//     //      //      //    ////////    ////////  //    //  //  //    //      ////    //    //    
//     //      //      //    //    //              //        //        //    //  ////    //  //    
//     //      //      //    ////////  //          //    //  //  //    //  //    //  //  //  //    
//     //      //      //    //    //  //    //    //  //    //    //  //      //        //  //    
//     ////////        //    ////////  //  //      //        //        //  //////////    //  //    
// ////      //        //    //    //  ////    //  //      ////        //    //    //      //      
//         //          //    //    //  //      //  //                  //      ////      //  //    
//       //        ////      //  ////    ////////  //////////////////////  ////    //  //      //  
//
//**************************************************************************************************

	private JSONObject doRequest(String methond, String api, Hashtable params) throws NotesException
	{
		JSONObject result = null;
		StringBuffer responseBuffer = null;

		try {
			if (methond.equals(HttpConnection.POST))
			{
				responseBuffer = checkResponse(_http.doPost(api, params));	
			} else {
				responseBuffer = checkResponse(_http.doGet(api, params));
			}

			if ((responseBuffer == null) || (responseBuffer.length() <= 0)) {result = null;}

			result = new JSONObject(new JSONTokener(new String(responseBuffer.toString().getBytes(), "utf-8")));
		} catch (Exception e) {
			throw new NotesException(e.getMessage());
		}

		return result;
	}

	public StringBuffer checkResponse(StringBuffer result) throws NotesException
	{
		try {
			if ((result != null) && (result.length() > 0)) {
				if ((result.charAt(0) == '{') && (result.charAt(result.length() - 1) == '}'))
				{
					JSONObject jo = new JSONObject(new JSONTokener(result.toString()));
					if ((jo != null) && jo.has("error"))
					{
						JSONObject jsonObject = jo.getJSONObject("error");

						String request = jsonObject.optString("request");
						int errorCode = jsonObject.optInt("errorCode");
						String errorMessage = new String(jsonObject.optString("errorMessage").getBytes(), "utf-8");
						throw new NotesException("\n\nrequest: " + request + "\nerrorCode: " + errorCode + "\nerrorMessage: " + errorMessage);
					}
				}
			}
		} catch (JSONException e) {Function.errorDialog(e.toString());}
		  catch (UnsupportedEncodingException e) {Function.errorDialog(e.toString());}

		return result;
	}
}

class ComparatorObject implements Comparator
{
	public int compare (Object key1,Object key2)
	{
		return ((((String) key1).compareTo((String) key2)));
	}
}